<template>
<div class="machine">
  <div class="machine_container" ref="container" id="container">
    <div
      class="machine_container_slider"
      ref="slider"
      id="slider"
    >
      <el-icon v-if="status !== 2" style="color:#e60012"><Lock /></el-icon>
      <el-icon v-else style="color:#00CC66"><Select /></el-icon>
    </div>
    <div class="successProcess"></div>
  </div>
</div>

<div class="imgValidate">
  <div class="imgValidate_content">
    <div class="imgValidate_content_img">
      <canvas id="canvas" width="300"  height="80" ref="canvasRef"></canvas>
      <div class="imgValidate_content_img_reload" @click="resetValidate">
        <el-icon><Refresh /></el-icon>
      </div>
    </div>
    <div
      class="imgValidate_content_btn"
      :class="{
        imgValidate_content_btn_success:validateStatus === 1,
        imgValidate_content_btn_error:validateStatus === -1,
      }"
    >
      <span class="normal" v-if="validateStatus === 0">请按语序依次点击文字</span>
      <span class="success" v-if="validateStatus === 1">验证成功,点击登录</span>
      <span class="error" v-if="validateStatus === -1" @click="resetValidate">验证失败，点击重试</span>
    </div>
  </div>
  <img :src="imgUrl('validateBg.jpg')" id="validateBg" style="display: none" alt="">
</div>
</template>

<script setup>
import imgUrl from "@/utils/loadImg";
import { computed, nextTick, onMounted, onUnmounted, ref, shallowRef, watch } from "vue";
const container = ref(null)
const slider = ref(null)
const containerWidth = ref(0)
const sliderWidth = ref(0)
const sliderLeft = ref(0)
const allowMoveDistance = computed(() => containerWidth.value - sliderWidth.value)

const sliderLeftPx = computed(() => sliderLeft.value + 'px')
const processLeftPx = computed(() => {
  return (sliderLeft.value - 250) + 'px'
})

const beginX = ref(0)
const status = ref(0) // 0-静止状态可拖拽，1-移动状态，2-结束状态不可拖拽
onMounted(() => {
  containerWidth.value = container.value.getClientRects()[0].width
  sliderWidth.value = slider.value.getClientRects()[0].width

  nextTick(() => {
    slider.value.addEventListener('mousedown',function(e){
      beginX.value = e.clientX
      status.value = 1
    })
    slider.value.addEventListener('mouseup',function(e){
      const moveDistance = e.clientX - beginX.value
      if(moveDistance < allowMoveDistance.value){
        sliderLeft.value = 0
        status.value = 0
      }else{
        sliderLeft.value = allowMoveDistance.value
        status.value = 2
      }
    })
    document.body.addEventListener('mouseup',function(){
      if(status.value === 1){
        sliderLeft.value = 0
        status.value = 0
      }
    })
    container.value.addEventListener('mousemove',function(e){
      if(status.value === 1){
        const moveDistance = e.clientX - beginX.value
        if(moveDistance <= 0 ) return
        if(moveDistance < allowMoveDistance.value){
          sliderLeft.value = moveDistance
        }else{
          sliderLeft.value = allowMoveDistance.value
          status.value = 2
        }
      }
    })
  })
})
onUnmounted(() => {
  document.body.removeEventListener('mouseup',function(){})
})

const textEnum = {
  0:['恭','喜','发','财'],
  1:['万','事','如','意'],
  2:['鹏','程','万','里'],
  3:['早','生','贵','子'],
  4:['白','头','偕','老'],
  5:['善','罢','甘','休'],
  6:['画','龙','点','睛'],
  7:['紫','气','东','来'],
  8:['锦','上','添','花'],
  9:['鼋','博','智','能'],
  10:['江','南','大','学'],
}
const validateStatus = ref(0) // -1-验证失败，0-未验证，1验证成功
const txtLocationArr = ref([])//生成文字坐标集合
const clickLocationArr = ref([])//文字范围集合
const canvasRef = ref()
const ctxRef = shallowRef()
const maxWidth = ref(0)//画布最大宽度
const maxHeight = ref(0)//画布最大高度
const sort = ref(1)//点击计数
const space = 30
onMounted(() => {
  maxWidth.value = canvasRef.value.width
  maxHeight.value = canvasRef.value.height

  const el = document.getElementById('canvas')
  ctxRef.value = el.getContext("2d");
  nextTick(() => {
    setTimeout(() => {
      createCanvasBg().then(() => {
        const txtRandom = Math.floor(Math.random() * 11)
        txtLocationArr.value = textEnum[txtRandom]
        // console.log(txtLocationArr.value);
        createLocation(txtLocationArr.value)
      })
    },50)
  })

  canvasRef.value.addEventListener('click', function(e){
    if(clickLocationArr.value.some(d => e.offsetX >= d.x && e.offsetX <= d.x2 && e.offsetY >= d.y && e.offsetY <= d.y2 && d.sort === 0)){
      const index = clickLocationArr.value.findIndex(d => e.offsetX >= d.x && e.offsetX <= d.x2 && e.offsetY >= d.y && e.offsetY <= d.y2 && d.sort === 0)
      if(sort.value < 5){
        clickLocationArr.value[index].sort = sort.value
        ctxRef.value.save()
        ctxRef.value.fillStyle='rgba(0,204,102,.4)';
        ctxRef.value.beginPath()
        ctxRef.value.arc(e.offsetX,e.offsetY,8, 0, 2 * Math.PI)
        ctxRef.value.fill()
        ctxRef.value.restore()
        ctxRef.value.save()
        ctxRef.value.font = "14px serif";
        ctxRef.value.fillStyle='#ffffff';
        ctxRef.value.textAlign = "center";
        ctxRef.value.textBaseline = "middle";
        ctxRef.value.fillText(String(sort.value), e.offsetX,e.offsetY);
        ctxRef.value.restore()
        sort.value ++
      }
    }else{
      console.log('不在文字上');
    }
  })
})
watch(() => sort.value, () => {
  if(sort.value === 5){
    const validateArr = clickLocationArr.value.sort((a, b) => a.sort - b.sort).map(d => d.txt)
    const flag = txtLocationArr.value.every((d,idx) => {
      return d === validateArr[idx]
    })
    if(flag){
      validateStatus.value = 1
    }else{
      validateStatus.value = -1
    }
  }
})
const createCanvasBg = () => {
  return new Promise((resolve) => {
    canvasRef.value.width = 300
    const img = document.getElementById('validateBg');
    ctxRef.value.save()
    ctxRef.value.drawImage(img,0,0)
    ctxRef.value.restore()
    resolve()
  })
}
const createLocation = (arr) => {
  arr.forEach(d => {
    // console.log(d);
    const obj = createXY()
    // console.log(obj);
    clickLocationArr.value.push({
      txt:d,
      x:obj.x,
      y:obj.y,
      x1: obj.x - space,
      x2: obj.x + space,
      y1: obj.y - space,
      y2: obj.y + space,
      sort:0
    })
    ctxRef.value.save()
    ctxRef.value.font = `${space}px serif`;
    ctxRef.value.fillStyle=`rgb(${Math.floor(Math.random() * 200)},${Math.floor(Math.random() * 200)},${Math.floor(Math.random() * 200)})`;
    ctxRef.value.textAlign = "left";
    ctxRef.value.textBaseline = "top";
    ctxRef.value.fillText(d, obj.x, obj.y);
    ctxRef.value.restore()
  })
}
const createXY = () => {
  const x = Math.floor(Math.random() * (maxWidth.value - space * 2))
  const y = Math.floor(Math.random() * (maxHeight.value - space))
  if(clickLocationArr.value.some(d => x >= d.x1 && x <= d.x2 && y >= d.y1 && y <= d.y2)){
    return  createXY()
  }else{
    return {x,y}
  }
}

const resetValidate = () => {
  validateStatus.value = 0
  sort.value = 1
  clickLocationArr.value = []
  createCanvasBg().then(() => {
    const txtRandom = Math.floor(Math.random() * 11)
    txtLocationArr.value = textEnum[txtRandom]
    createLocation(txtLocationArr.value)
  })
}
</script>

<style scoped lang="scss">
  .machine{
    &_container{
      width:300px;
      height:50px;
      border:1px solid #ddd;
      margin: 100px 0 0 200px;
      position: relative;
      overflow: hidden;
      .successProcess{
        position: absolute;
        width:250px;
        height:100%;
        background: #00CC66;
        z-index: 10;
        left:v-bind('processLeftPx');
      }
      &_slider{
        width:50px;
        height:50px;
        background: #f1f1f1;
        cursor: pointer;
        position: absolute;
        z-index: 11;
        top:0;
        left:v-bind('sliderLeftPx');
        display: flex;
        ::v-deep(.el-icon){
          margin:auto;
        }
      }
    }
  }
  .imgValidate{
    margin-top: 50px;
    margin-left: 200px;
    &_content{
      &_img{
        position: relative;
        width: 300px;
        height:80px;
        margin-bottom: 10px;
        #canvas{
          background: #f5f5f5;
          position: absolute;
          top:0;
          left:0;
          z-index: 10;
        }
        &_reload{
          position: absolute;
          width: 20px;
          height:20px;
          display: flex;
          top:0;
          right:0;
          z-index: 12;
          ::v-deep(.el-icon){
            margin:auto;
            cursor: pointer;
            color:#999999;
          }
        }
      }
      &_btn{
        height:40px;
        width: 300px;
        border:1px solid #ddd;
        border-radius: 5px;
        font-size: 14px;
        text-align: center;
        line-height: 40px;
        color:#333;
        background: #F8FAFE;
        user-select: none;
        transition: all .15s linear;
        &_success{
          color: #62D0C2;
          background: linear-gradient(to bottom, #E3FFF9, #C8F6EE);
          border-color: #A1E8DD;
          cursor: pointer;
        }
        &_error{
          color: #FF0000;
          background: linear-gradient(to bottom, #FFCCCC, #FFCC99);
          border-color: #FF6600;
          cursor: pointer;
        }
      }
    }
  }
  @keyframes iconRotate {
    0%{
      transform: rotate(0deg);
    }
    100%{
      transform: rotate(360deg);
    }
  }
</style>